/**
 * 预约管理 IPC 处理器
 *
 * @fileoverview 预约管理模块的IPC通信处理器，负责主进程与渲染进程之间的数据交换。
 * 提供预约记录的CRUD操作、批量处理、Excel导入导出、快速预约、占号管理等功能的IPC接口。
 *
 * 核心功能：
 * - 预约记录管理（增删改查）
 * - 批量操作处理
 * - Excel数据导入导出
 * - 快速预约配置
 * - 占号数据管理
 * - 操作日志记录
 * - 数据序列化处理
 *
 * @author System
 * @version 1.0.0
 * @since 2024
 *
 * @example
 * ```typescript
 * // 在主进程初始化时调用
 * import { setupAppointmentHandlers } from './appointment-handlers'
 *
 * // 注册所有预约相关的IPC处理器
 * setupAppointmentHandlers()
 * ```
 */

import type {
  AppointmentFilters,
  BatchOperationRequest,
  CreateAppointmentInput,
  PaginationParams,
  UpdateAppointmentInput,
} from '@shared/types/appointment'
import { ipcMain } from 'electron'
import { getLogger } from '../logger/index'
import { getAppointmentService } from '../services/appointment-service'
import { getExcelImportService } from '../services/excel-import-service'
import { getPlaceholderService } from '../services/placeholder-service'

/**
 * 设置预约管理相关的IPC处理器
 *
 * @description 注册所有预约管理相关的IPC事件处理器，包括CRUD操作、批量处理、
 * Excel导入导出、快速预约等功能。每个处理器都包含错误处理和数据序列化。
 *
 * @returns {void}
 *
 * @example
 * ```typescript
 * // 在主进程的入口文件中调用
 * setupAppointmentHandlers()
 *
 * // 然后在渲染进程中可以通过IPC调用：
 * const result = await window.api.appointment.create(appointmentData)
 * ```
 */
export function setupAppointmentHandlers(): void {
  const logger = getLogger()
  const appointmentService = getAppointmentService()
  const excelService = getExcelImportService()
  const placeholderService = getPlaceholderService()

  /**
   * 数据序列化工具函数
   *
   * @description 将要通过IPC返回的数据清洗为可结构化克隆的纯数据，
   * 处理Vue代理对象、Date对象、函数等不可序列化的数据类型。
   *
   * @param {any} value - 要序列化的数据
   * @returns {any} 序列化后的纯数据
   * @private
   */
  function toPlainSerializable(value: any): any {
    if (value === null || value === undefined)
      return value
    const type = typeof value
    if (type === 'string' || type === 'number' || type === 'boolean')
      return value
    if (type === 'bigint')
      return Number(value)
    if (type === 'function' || type === 'symbol')
      return undefined
    if (value instanceof Date)
      return value.toISOString()
    if (typeof ArrayBuffer !== 'undefined') {
      const AB: any = ArrayBuffer as any
      if (value instanceof ArrayBuffer)
        return value
      if (AB.isView && AB.isView(value))
        return value
    }
    if (Array.isArray(value))
      return value.map(v => toPlainSerializable(v)).filter(v => v !== undefined)
    try {
      const plain: Record<string, any> = {}
      for (const key of Object.keys(value)) {
        const v = toPlainSerializable((value as any)[key])
        if (v !== undefined)
          plain[key] = v
      }
      return plain
    }
    catch {
      try {
        return JSON.parse(JSON.stringify(value))
      }
      catch {
        return undefined
      }
    }
  }

  // ============================================================================
  // 预约记录 CRUD 操作
  // ============================================================================

  /**
   * IPC处理器：创建预约记录
   *
   * @description 处理来自渲染进程的预约记录创建请求
   * @channel appointment:create
   * @param {CreateAppointmentInput} input - 预约记录创建数据
   * @returns {Promise<{success: boolean, data?: any, error?: string}>} 操作结果
   */
  ipcMain.handle('appointment:create', async (_event, input: CreateAppointmentInput) => {
    try {
      const appointment = await appointmentService.createAppointment(input)
      return { success: true, data: toPlainSerializable(appointment) }
    }
    catch (error: any) {
      logger.error('创建预约记录失败:', error)
      return { success: false, error: error.message }
    }
  })

  /**
   * IPC处理器：获取预约记录
   *
   * @description 根据ID获取单个预约记录的详细信息
   * @channel appointment:get
   * @param {number} id - 预约记录ID
   * @returns {Promise<{success: boolean, data?: any, error?: string}>} 操作结果
   */
  ipcMain.handle('appointment:get', async (_event, id: number) => {
    try {
      const appointment = await appointmentService.getAppointment(id)
      return { success: true, data: toPlainSerializable(appointment) }
    }
    catch (error: any) {
      logger.error('获取预约记录失败:', error)
      return { success: false, error: error.message }
    }
  })

  /**
   * IPC处理器：更新预约记录
   *
   * @description 更新指定ID的预约记录信息
   * @channel appointment:update
   * @param {number} id - 预约记录ID
   * @param {UpdateAppointmentInput} input - 更新数据
   * @returns {Promise<{success: boolean, data?: any, error?: string}>} 操作结果
   */
  ipcMain.handle('appointment:update', async (_event, id: number, input: UpdateAppointmentInput) => {
    try {
      const appointment = await appointmentService.updateAppointment(id, input)
      return { success: true, data: toPlainSerializable(appointment) }
    }
    catch (error: any) {
      logger.error('更新预约记录失败:', error)
      return { success: false, error: error.message }
    }
  })

  /**
   * IPC处理器：删除预约记录
   *
   * @description 删除指定ID的预约记录
   * @channel appointment:delete
   * @param {number} id - 预约记录ID
   * @returns {Promise<{success: boolean, error?: string}>} 操作结果
   */
  ipcMain.handle('appointment:delete', async (_event, id: number) => {
    try {
      await appointmentService.deleteAppointment(id)
      return { success: true }
    }
    catch (error: any) {
      logger.error('删除预约记录失败:', error)
      return { success: false, error: error.message }
    }
  })

  // ============================================================================
  // 查询和批量操作
  // ============================================================================

  /**
   * IPC处理器：查询预约记录列表
   *
   * @description 根据过滤条件和分页参数查询预约记录列表
   * @channel appointment:list
   * @param {AppointmentFilters} filters - 查询过滤条件
   * @param {PaginationParams} pagination - 分页参数
   * @returns {Promise<{success: boolean, data?: any, error?: string}>} 操作结果
   */
  ipcMain.handle('appointment:list', async (_event, filters: AppointmentFilters, pagination: PaginationParams) => {
    try {
      const result = await appointmentService.getAppointmentsList(filters, pagination)
      return { success: true, data: toPlainSerializable(result) }
    }
    catch (error: any) {
      logger.error('查询预约记录失败:', error)
      return { success: false, error: error.message }
    }
  })

  /**
   * IPC处理器：批量操作
   *
   * @description 对多个预约记录执行批量操作（删除、取消、更新优先级等）
   * @channel appointment:batch-operation
   * @param {BatchOperationRequest} request - 批量操作请求数据
   * @returns {Promise<{success: boolean, data?: any, error?: string}>} 操作结果
   */
  ipcMain.handle('appointment:batch-operation', async (_event, request: BatchOperationRequest) => {
    try {
      const result = await appointmentService.batchOperation(request)
      return { success: true, data: toPlainSerializable(result) }
    }
    catch (error: any) {
      logger.error('批量操作失败:', error)
      return { success: false, error: error.message }
    }
  })

  // ============================================================================
  // 统计信息和日志
  // ============================================================================

  /**
   * IPC处理器：获取统计信息
   *
   * @description 获取预约系统的各项统计数据
   * @channel appointment:statistics
   * @returns {Promise<{success: boolean, data?: any, error?: string}>} 统计信息
   */
  ipcMain.handle('appointment:statistics', async (_event) => {
    try {
      const stats = await appointmentService.getStatistics()
      return { success: true, data: toPlainSerializable(stats) }
    }
    catch (error: any) {
      logger.error('获取统计信息失败:', error)
      return { success: false, error: error.message }
    }
  })

  /**
   * IPC处理器：获取操作日志
   *
   * @description 获取指定预约记录的操作日志历史
   * @channel appointment:operation-logs
   * @param {number} appointmentId - 预约记录ID
   * @returns {Promise<{success: boolean, data?: any, error?: string}>} 操作日志列表
   */
  ipcMain.handle('appointment:operation-logs', async (_event, appointmentId: number) => {
    try {
      const logs = await appointmentService.getOperationLogs(appointmentId)
      return { success: true, data: toPlainSerializable(logs) }
    }
    catch (error: any) {
      logger.error('获取操作日志失败:', error)
      return { success: false, error: error.message }
    }
  })

  // ============================================================================
  // Excel 导入导出功能
  // ============================================================================

  /**
   * IPC处理器：Excel导入
   *
   * @description 从Excel文件导入预约记录数据
   * @channel excel:import
   * @param {string} filePath - Excel文件路径
   * @returns {Promise<{success: boolean, data?: any, error?: string}>} 导入结果
   */
  ipcMain.handle('excel:import', async (_event, filePath: string) => {
    try {
      const result = await excelService.importFromExcel(filePath)
      return { success: true, data: result }
    }
    catch (error: any) {
      logger.error('Excel导入失败:', error)
      return { success: false, error: error.message }
    }
  })

  ipcMain.handle('excel:generate-template', async (_event) => {
    try {
      const buffer = await excelService.generateTemplate()
      return { success: true, data: buffer }
    }
    catch (error: any) {
      logger.error('生成Excel模板失败:', error)
      return { success: false, error: error.message }
    }
  })

  ipcMain.handle('excel:export', async (_event, appointmentIds?: number[]) => {
    try {
      const buffer = await excelService.exportToExcel(appointmentIds)
      return { success: true, data: buffer }
    }
    catch (error: any) {
      logger.error('导出Excel失败:', error)
      return { success: false, error: error.message }
    }
  })

  // 按筛选导出（渲染进程传入 AppointmentFilters，与列表页筛选一致）
  ipcMain.handle('excel:export-by-filters', async (_event, filters: any) => {
    try {
      const buffer = await excelService.exportByFilters(filters || {})
      return { success: true, data: buffer }
    }
    catch (error: any) {
      logger.error('按筛选导出Excel失败:', error)
      return { success: false, error: error.message }
    }
  })


  // 文件对话框
  ipcMain.handle('dialog:open-file', async (_event, options: any) => {
    try {
      const { dialog } = await import('electron')
      const result = await dialog.showOpenDialog(options)
      return { success: true, data: result }
    }
    catch (error: any) {
      logger.error('打开文件对话框失败:', error)
      return { success: false, error: error.message }
    }
  })

  ipcMain.handle('dialog:save-file', async (_event, options: any) => {
    try {
      const { dialog } = await import('electron')
      const result = await dialog.showSaveDialog(options)
      return { success: true, data: result }
    }
    catch (error: any) {
      logger.error('保存文件对话框失败:', error)
      return { success: false, error: error.message }
    }
  })

  // 占号数据管理
  ipcMain.handle('placeholder:generate-single', async (_event, options: any) => {
    try {
      const id = await placeholderService.generateSinglePlaceholder(options)
      return { success: true, data: { id } }
    }
    catch (error: any) {
      logger.error('生成单个占号数据失败:', error)
      return { success: false, error: error.message }
    }
  })

  ipcMain.handle('placeholder:generate-batch', async (_event, options: any) => {
    try {
      const result = await placeholderService.generateBatchPlaceholders(options)
      return { success: true, data: result }
    }
    catch (error: any) {
      logger.error('批量生成占号数据失败:', error)
      return { success: false, error: error.message }
    }
  })

  ipcMain.handle('placeholder:generate-for-appointment', async (_event, appointmentId: number, count: number) => {
    try {
      const result = await placeholderService.generatePlaceholdersForAppointment(appointmentId, count)
      return { success: true, data: result }
    }
    catch (error: any) {
      logger.error('为预约生成占号数据失败:', error)
      return { success: false, error: error.message }
    }
  })

  ipcMain.handle('placeholder:statistics', async (_event) => {
    try {
      const stats = await placeholderService.getPlaceholderStatistics()
      return { success: true, data: stats }
    }
    catch (error: any) {
      logger.error('获取占号数据统计失败:', error)
      return { success: false, error: error.message }
    }
  })

  ipcMain.handle('placeholder:cleanup-by-ids', async (_event, placeholderIds: number[]) => {
    try {
      const count = await placeholderService.cleanupPlaceholdersByIds(placeholderIds)
      return { success: true, data: { cleaned_count: count } }
    }
    catch (error: any) {
      logger.error('清理指定占号数据失败:', error)
      return { success: false, error: error.message }
    }
  })

  ipcMain.handle('placeholder:release-by-ids', async (_event, placeholderIds: number[]) => {
    try {
      const count = await placeholderService.releasePlaceholdersByIds(placeholderIds)
      return { success: true, data: { released_count: count } }
    }
    catch (error: any) {
      logger.error('释放指定占号数据失败:', error)
      return { success: false, error: error.message }
    }
  })

  logger.info('✅ 预约管理 IPC 处理器注册完成')
}
